home *** CD-ROM | disk | FTP | other *** search
/ Mac Power 1997 December / MACPOWER-1997-12.ISO.7z / MACPOWER-1997-12.ISO / AMUG / PROGRAMMING / Raven 1.2.sit / Raven 1.2 / Source / Foundation / Common / ZProfiler.cpp < prev    next >
Text File  |  1997-09-06  |  6KB  |  223 lines

  1. /*
  2.  *  File:       ZProfiler.cpp
  3.  *  Summary:       Stack based class used to profile blocks of code.
  4.  *  Written by: Jesse Jones
  5.  *
  6.  *  Copyright ゥ 1996-1997 Jesse Jones. 
  7.  *    For conditions of distribution and use, see copyright notice in ZTypes.h  
  8.  *
  9.  *  Change History (most recent first):    
  10.  *
  11.  *         <4>     9/05/97    JDJ        Uses bestTimeBase instead of microsecondsTimeBase.
  12.  *                                    Warning for too small numFunctions and stackDepth
  13.  *                                    now reports correct required values. Dtor uses
  14.  *                                    BreakStrToDebugger instead of an ASSERT on error.
  15.  *         <3>     7/27/97    JDJ        Added Enable and Disable methods.
  16.  *         <2>     3/31/97    JDJ        Uses BreakStrToDebugger.
  17.  *         <1>    12/05/96    JDJ        Created
  18.  */
  19.  
  20. #include <ZProfiler.h>
  21.  
  22. #include <StdIO.h>
  23.  
  24. #include <ZDebug.h>
  25. #include <ZExceptions.h>
  26. #include <ZStringUtils.h>
  27.  
  28.  
  29. #if    __profile__            // all methods are stubbed out in the header if profiling is off
  30.  
  31. #pragma profile off        // donユt profile these
  32.  
  33.  
  34. //-----------------------------------
  35. //    Constants
  36. //
  37. const long kNumFunctionsEntrySize = 12*64L;
  38. const long kStackDepthEntrySize   = 40;
  39.  
  40.  
  41. //================================================================================
  42. // class TProfiler
  43. //================================================================================
  44.  
  45. //---------------------------------------------------------------
  46. //
  47. // GetValidName
  48. //
  49. // From UFileSystem.cpp
  50. //
  51. //---------------------------------------------------------------
  52. static string GetValidName(const string& name, long maxLen = 31)
  53. {
  54.     ASSERT(maxLen <= 31);
  55.     
  56.     string outName = name;
  57.     
  58.     // Replace colons with dashes (like the Finder).
  59.     for (short index = 0; index < outName.length(); index++) {
  60.         if (outName[index] == ':')
  61.             outName[index] = '-';
  62.     }
  63.     
  64.     // Truncate from the middle if the name is too large.
  65.     if (outName.length() > maxLen) {
  66.         size_t overflow = (outName.length() - maxLen) + 1;
  67.         
  68.         size_t first = outName.length()/2 - overflow/2;        // first character we're going to drop
  69.         size_t last  = first + overflow - 1;                // last character we're going to drop
  70.         
  71.         outName = outName.substr(0, first) + "ノ" + outName.substr(last + 1);
  72.         ASSERT(outName.length() <= maxLen);
  73.     }
  74.     
  75.     return outName;
  76. }
  77.  
  78. #pragma mark -
  79.  
  80. //================================================================================
  81. // class TProfiler
  82. //================================================================================
  83.  
  84. bool TProfiler::msConstructed = false;
  85.  
  86. //---------------------------------------------------------------
  87. //
  88. // TProfiler::~TProfiler
  89. //
  90. // ・・ハThe profiler is rather bogus in that you pass the number of
  91. // ・・ハfunctions and the stack depth into ProfilerInit. However to
  92. // ・・ハtest if these numbers are large enough you call ProfilerGetDataSizes
  93. // ・・ハwhich returns the sizes of the profiler's internal buffers. 
  94. // ・・ハThe relation between these two sets of numbers is documented, 
  95. // ・・ハbut there's no constant declared in Profiler.h and no guarantee
  96. // ・・ハthat the values won't change in the future.
  97. //
  98. //---------------------------------------------------------------
  99. TProfiler::~TProfiler()
  100. {
  101.     char str[256];
  102.  
  103.     long functionBytes, stackBytes;
  104.     ProfilerGetDataSizes(&functionBytes, &stackBytes);
  105.  
  106.     long numFunctions = functionBytes/kNumFunctionsEntrySize;
  107.     long stackDepth = stackBytes/kStackDepthEntrySize;
  108.  
  109.     if (numFunctions > mNumFunctions) {
  110.         sprintf(str, "numFunctions is too small. It should be %d.", numFunctions);    // Profiling is often done in !RELEASE builds so we can't use TRACE or DEBUGSTR.
  111.         BreakStrToDebugger(str);
  112.     }
  113.  
  114.     if (stackDepth > mStackSize) {
  115.         sprintf(str, "stackDepth is too small. It should be %d.", stackDepth);
  116.         BreakStrToDebugger(str);
  117.     }
  118.         
  119.     OSErr err = ProfilerDump(StrToPStr(mFileName));
  120.     if (err != noErr)
  121.         BreakStrToDebugger("Got an error calling ProfilerDump");
  122.  
  123.     ProfilerTerm();
  124.     
  125.     msConstructed = false;
  126. }
  127.  
  128.  
  129. //---------------------------------------------------------------
  130. //
  131. // TProfiler::TProfiler
  132. //
  133. //---------------------------------------------------------------
  134. TProfiler::TProfiler(const string& fileName, short numFunctions, short stackDepth)
  135. {
  136.     ASSERT(fileName.length() > 0);
  137.     ASSERT(numFunctions > 0);
  138.     ASSERT(stackDepth > 0);
  139.     ASSERT(!msConstructed);                    // profiler library isn't nestable
  140.  
  141.     mFileName = GetValidName(fileName, 30);    // ProfilerDump fails with a weird error if you use colons or the name is too long (CW 11)
  142.     mNumFunctions = numFunctions;
  143.     mStackSize = stackDepth;
  144.     
  145.     OSErr err = ProfilerInit(collectDetailed, bestTimeBase, numFunctions, stackDepth);
  146.     ThrowIfOSErr(err);
  147.     
  148.     mEnableCount = 1;
  149.     
  150.     msConstructed = true;
  151. }
  152.  
  153.  
  154. //---------------------------------------------------------------
  155. //
  156. // TProfiler::IsEnabled
  157. //
  158. //---------------------------------------------------------------
  159. bool TProfiler::IsEnabled() const            
  160. {
  161.     return mEnableCount > 0;
  162. }
  163.  
  164.  
  165. //---------------------------------------------------------------
  166. //
  167. // TProfiler::Enable
  168. //
  169. //---------------------------------------------------------------
  170. void TProfiler::Enable()
  171. {
  172.     mEnableCount++;
  173.     
  174.     if (mEnableCount == 1)
  175.         ProfilerSetStatus(true);
  176. }
  177.  
  178.  
  179. //---------------------------------------------------------------
  180. //
  181. // TProfiler::Disable
  182. //
  183. //---------------------------------------------------------------
  184. void TProfiler::Disable()
  185. {    
  186.     mEnableCount--;
  187.     
  188.     if (mEnableCount == 0)
  189.         ProfilerSetStatus(false);
  190. }
  191.  
  192. #pragma mark -
  193.  
  194. //================================================================================
  195. // class TProfileEnabler
  196. //================================================================================
  197.  
  198. //---------------------------------------------------------------
  199. //
  200. // TProfileEnabler::~TProfileEnabler
  201. //
  202. //---------------------------------------------------------------
  203. TProfileEnabler::~TProfileEnabler()
  204. {
  205.     ProfilerSetStatus(mWasEnabled);
  206. }
  207.  
  208.  
  209. //---------------------------------------------------------------
  210. //
  211. // TProfileEnabler::TProfileEnabler
  212. //
  213. //---------------------------------------------------------------
  214. TProfileEnabler::TProfileEnabler()
  215. {
  216.     mWasEnabled = (bool) ProfilerGetStatus();
  217.     ProfilerSetStatus(true);
  218. }
  219.  
  220.  
  221. #endif    // __profile__
  222.  
  223.